
public class Main {
	public static void main(String args[]) {
		Expr m1, m2;
		m1 = new Sum(new Number(1), new Number(2));
		m2 = new Sum(new Number(5), new Number(0));
		Expr root = new Mult(m1, m2);
		ElementVisitor element = (ElementVisitor) root;
		element.accept(new PrintVisitor());
	}
	
	public static aspect VisitorAspect {
		declare parents: Expr extends ElementVisitor;		

		public void Exp+.accept(Visitor v) {
			v.visit(this);
		}
	}
	
	static interface Expr {
		
	}
	
	static class Sum implements Expr {
		private Expr ex1, ex2;
		
		public Sum(Expr ex1, Expr ex2) {
			this.ex1 = ex1;
			this.ex2 = ex2;
		}
		
		public String toString() {
			return ex1 + "+" + ex2;
		}
	}
	
	static class Mult implements Expr {
		private Expr ex1, ex2;
		
		public Mult(Expr ex1, Expr ex2) {
			this.ex1 = ex1;
			this.ex2 = ex2;
		}
		
		public String toString() {
			return ex1 + "*" + ex2;
		}
	}
	
	static class Number implements Expr {
		private int number;
		
		public Number(int number) {
			this.number = number;
		}
		
		public String toString() {
			String resp = "" + number;
			return resp;
		}
	}

	static interface ElementVisitor {
		void accept(Visitor v);
	}
	
	static interface Visitor {
		void visit(Sum expr);
		void visit(Mult expr);
		void visit(Number expr);
	}
	
	static class PrintVisitor implements Visitor {
		public void visit(Sum expr) {
			System.out.print(expr.toString());
		}

		public void visit(Mult expr) {
			System.out.print(expr.toString());
		}

		public void visit(Number expr) {
			System.out.print(expr.toString());		
		}
	}
}
